# -*- coding: utf-8 -*-

from datetime import date, datetime, timedelta
from Settings.config import Config
import pytz
import string
import random
import hashlib
import logging
import inspect
from Utility.error_code import error_code
from io import BytesIO
import pandas as pd

DATE_FORMAT = "%Y-%m-%d"
TIME_FORMAT = "%H:%M:%S"
DATETIME_FORMAT = "%s %s" % (DATE_FORMAT, TIME_FORMAT)
DATE_LENGTH = len(date.today().strftime(DATE_FORMAT))
DATETIME_LENGTH = len(datetime.now().strftime(DATETIME_FORMAT))

_logger = logging.getLogger(__name__)


def context_today(timestamp=None):
    """ Return the current date as seen in the client's timezone in a format
        fit for date fields. This method may be used to compute default
        values.

        :param datetime timestamp: optional datetime value to use instead of
            the current date and time (must be a datetime, regular dates
            can't be converted between timezones.)
        :rtype: str
    """
    today = timestamp or datetime.now()
    context_today = None
    tz_name = Config.CLIENT_TZ
    if tz_name:
        try:
            today_utc = pytz.timezone('UTC').localize(
                today, is_dst=False)  # UTC = no DST
            context_today = today_utc.astimezone(pytz.timezone(tz_name))
        except Exception:
            _logger.debug(
                "failed to compute context/client-specific today date, using UTC value for `today`",
                exc_info=True)
    return (context_today or today).strftime(DATE_FORMAT)


def from_string(value):
    """ Convert an ORM ``value`` into a :class:`date` value. """
    if not value:
        return None
    value = value[:DATE_LENGTH]
    return datetime.strptime(value, DATE_FORMAT).date()


def to_string(value):
    """ Convert a :class:`date` value into the format expected by the ORM. """
    return value.strftime(DATE_FORMAT) if value else False


def get_context_year():
    """获取客户端时区的当前年"""
    return from_string(context_today()).strftime('%Y')


def get_context_month():
    """获取客户端时区的当前月份"""
    month = from_string(context_today()).strftime('%m')
    month = str(int(month))
    return month


def get_context_day():
    """获取客户端时区的当前日"""
    day = from_string(context_today()).strftime('%d')
    day = str(int(day))
    return day


def context_timestamp(timestamp=None):
    """Returns the given timestamp converted to the client's timezone.
       This method is *not* meant for use as a default initializer,
       because datetime fields are automatically converted upon
       display on client side. For default values :meth:`fields.datetime.now`
       should be used instead.

       :param datetime timestamp: naive datetime value (expressed in UTC)
                                  to be converted to the client timezone
       :rtype: datetime
       :return: timestamp converted to timezone-aware datetime in context
                timezone
    """
    timestamp = timestamp or datetime.now()
    tz_name = Config.CLIENT_TZ
    utc_timestamp = pytz.utc.localize(timestamp, is_dst=False)  # UTC = no DST
    if tz_name:
        try:
            context_tz = pytz.timezone(tz_name)
            return (utc_timestamp.astimezone(context_tz)
                    or timestamp).strftime(DATETIME_FORMAT)
        except Exception:
            _logger.debug(
                "failed to compute context/client-specific timestamp, "
                "using the UTC value",
                exc_info=True)
    return utc_timestamp


def getSign(transactionId):
    md5 = hashlib.md5()
    md5.update((transactionId + Config.SECRET_KEY).encode("utf8"))
    return md5.hexdigest()


def generate_nonce_str(length=32):
    return ''.join(random.SystemRandom().choice(string.ascii_letters +
                                                string.digits)
                   for _ in range(length))


"""类转字典"""


def class_to_dict(obj):
    result = {}
    for name in dir(obj):
        value = getattr(obj, name)
        if not name.startswith('__') and not callable(value):
            result[name] = value
    return result


def get_params(request):
    params = {}
    headers = request.headers
    method = request.method
    if method == "GET":
        params = request.args
    elif method == "POST":
        content_type = headers.get('Content-Type')
        if "www-form" in content_type:  # 表单请求
            params = request.form
        elif "application/json" in content_type:  # json请求
            params = request.get_json()
    return params


# 这是从堆栈内存的第3层开始查找返回变量名称
def retrieve_name(var):
    for fi in inspect.stack()[2:]:
        for item in fi.frame.f_locals.items():
            if var is item[1]:
                return item[0]
    return ""


#  必填参数校验
def required_parame_verif(req_parames, params):
    '''
    params_ = params 
    if instance(params,list):
        params_ = {}
        for param in params:
            params_[param[1]]=param[-1]
    '''
    for parame in req_parames:
        try:
            if parame not in params.keys():
                return {'code': 300, 'msg': error_code[300].format(parame)}
            if not params.get(parame):
                return {'code': 413, 'msg': error_code[413].format(parame)}
        except Exception as e:
            return {'code': 412, 'msg': error_code[412]}
    return {'code': 0, 'msg': 'success', 'data': {}, 'success': True}


def num_to_char(num):
    """数字转中文"""
    num_dict = {
        "0": u"零",
        "1": u"一",
        "2": u"二",
        "3": u"三",
        "4": u"四",
        "5": u"五",
        "6": u"六",
        "7": u"七",
        "8": u"八",
        "9": u"九"
    }
    num = str(num)
    new_str = ""
    listnum = list(num)
    shu = []
    for i in listnum:
        shu.append(num_dict[i])
    new_str = "".join(shu)
    return new_str


#  计算年龄
def calculate_age(born):
    birthDate = datetime.strptime(born, "%d/%m/%Y").date()
    currentDate = datetime.today().date()
    age = currentDate.year - birthDate.year
    monthVeri = currentDate.month - birthDate.month
    dateVeri = currentDate.day - birthDate.day
    age = int(age)
    monthVeri = int(monthVeri)
    dateVeri = int(dateVeri)
    if monthVeri < 0:
        age = age - 1
    elif dateVeri < 0 and monthVeri == 0:
        age = age - 1
    return age


# 根据身份证计算年龄
def calculate_age_by_card(card):
    birth_day = card[6:14]  #出生年月日
    birth_year = birth_day[0:4]  #前四位
    birth_month = birth_day[4:6]
    birth_date = birth_day[6:8]
    now = datetime.now()
    diff_year = now.year - int(birth_year)  #int换算
    diff_month = now.month - int(birth_month)
    diff_day = now.day - int(birth_date)
    if diff_month < 0 or diff_month == 0 and diff_day < 0:
        return diff_year - 1
    return diff_year


#  获取当前周
def get_current_week(date=None):
    if date:
        duty_date = datetime.strptime(str(date), '%Y-%m-%d')
        monday, sunday = duty_date, duty_date
    else:
        monday, sunday = datetime.today(), datetime.today()
    one_day = timedelta(days=1)
    while monday.weekday() != 0:
        monday -= one_day
    while sunday.weekday() != 6:
        sunday += one_day

    # return monday, sunday
    # 返回时间字符串
    return datetime.strftime(monday, "%Y-%m-%d"), datetime.strftime(
        sunday, "%Y-%m-%d")
